package com.softserveinc.ita.kaiji.multiplay.domain.card;

/**
 * Project kaiji-game
 * Created by mikeldpl
 * 28.03.2015 17:35.
 */
public class Card {

	public static final String back = "CARDBACK";
	private static final String[] names = new String[]{"STONE", "PAPER", "SCISSORS", "SPOK", "LIZARD"};
	private final int number;
	private final int numberOfTypes;

	public Card(int number, int numberOfTypes) {
		if (number >= names.length || number < 0 || numberOfTypes > names.length || numberOfTypes < 3)
			throw new InvalidDomainCardStateException("Invalid parameters of card");
		this.number = number;
		this.numberOfTypes = numberOfTypes;
	}

	public Card(String name, int numberOfTypes) {
		if (numberOfTypes > names.length || numberOfTypes < 3)
			throw new InvalidDomainCardStateException("Invalid parameters of card");
		this.numberOfTypes = numberOfTypes;
		int i = 0;
		for (; i < numberOfTypes; i++) {
			if (names[i].toUpperCase().equals(name)) {
				break;
			}
		}
		number = i;
		if (i == numberOfTypes)
			throw new InvalidDomainCardStateException("Invalid name of card");
	}

	public int getNumber() {
		return number;
	}

	public int getNumberOfTypes() {
		return numberOfTypes;
	}

	public String getName() {
		return names[number];
	}


	/**
	 * Compares two cards
	 *
	 * @param opponent Another Card entity to compare with
	 * @return Outcome enum: if cards are equals - DRAW,
	 * if first player won - WIN
	 * and LOSE if opponent won
	 */
	public DuelResult match(Card opponent) {
		if (getNumberOfTypes() != opponent.getNumberOfTypes())
			throw new InvalidDomainCardStateException("Invalid opponent of card");
		if (getNumber() == opponent.getNumber()) {
			return DuelResult.DRAW;
		}
		return (((getNumber() - opponent.getNumber() + getNumberOfTypes()) % getNumberOfTypes()) & 1) == 0
				? DuelResult.LOSE : DuelResult.WIN;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		Card card = (Card) o;

		if (number != card.number) return false;
		if (numberOfTypes != card.numberOfTypes) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = number;
		result = 31 * result + numberOfTypes;
		return result;
	}

	public enum DuelResult {
		WIN, LOSE, DRAW
	}
}
